package com.atguigu.exam.service.impl;


import com.atguigu.exam.entity.*;
import com.atguigu.exam.mapper.ExamRecordMapper;
import com.atguigu.exam.mapper.PaperMapper;
import com.atguigu.exam.mapper.QuestionMapper;
import com.atguigu.exam.service.PaperQuestionService;
import com.atguigu.exam.service.PaperService;
import com.atguigu.exam.vo.AiPaperVo;
import com.atguigu.exam.vo.PaperVo;
import com.atguigu.exam.vo.RuleVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.netty.util.internal.ObjectUtil;
import jodd.bean.BeanUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * 试卷服务实现类
 */
@Slf4j
@Service
public class PaperServiceImpl extends ServiceImpl<PaperMapper, Paper> implements PaperService {
    @Autowired
    private final QuestionMapper questionMapper;
    @Autowired
    private PaperQuestionService PaperQuestionService;
    @Autowired
    private ExamRecordMapper examRecordMapper;

    public PaperServiceImpl(QuestionMapper questionMapper) {
        this.questionMapper = questionMapper;
    }

    //根据试卷ID查询试卷详情
    @Override
    public Paper customPaperDetailById(Long id) {
        //单表Java 代码进行查询
        Paper paper = getById(id);
        // 校验paper == null ->抛异常
        if (paper == null) {
            throw new RuntimeException("查询的试卷不存在");
        }
        // 根据paperID查询试卷
        List<Question> questionList = questionMapper.customQueryQuestionListByPaperId(id);
        //校验题目集合 == null
        if (ObjectUtils.isEmpty(questionList)) {
            paper.setQuestions(new ArrayList<Question>());
            log.warn("查询的试卷下没有题目");
            return paper;
        }
        log.debug("题目信息排序前：{}", questionList);
        // 对题目进行排序
        questionList.sort((o1, o2) -> Integer.compare(typeToInt(o1.getType()), typeToInt(o2.getType())));
        log.debug("题目信息排序后：{}", questionList);
        paper.setQuestions(questionList);
        return paper;
    }

    @Override
    public Paper createPaper(PaperVo paperVo) {
        Paper paper = new Paper();
        BeanUtils.copyProperties(paperVo, paper);
        paper.setStatus("DRAFT");
        if (ObjectUtils.isEmpty(paperVo.getQuestions())) {
            paper.setTotalScore(BigDecimal.ZERO);
            paper.setQuestionCount(0);
            save(paper);
            log.info("本次{}试卷， 没有选题！");
            return paper;
        }
        paper.setQuestionCount(paperVo.getQuestions().size());
        paper.setTotalScore(paperVo.getQuestions().values().stream().reduce(BigDecimal.ZERO, BigDecimal::add));
        save(paper);
        List<PaperQuestion> paperQuestions = paperVo.getQuestions().entrySet().stream().
                map(entry -> new PaperQuestion(paper.getId().intValue(), Long.valueOf(entry.getKey()), entry.getValue())).
                collect(Collectors.toList());
        PaperQuestionService.saveBatch(paperQuestions);

        return paper;
    }

    //智能创建试卷（AI组卷）
    @Override
    public Paper createPaperWithAI(AiPaperVo aiPaperVo) {
        // 1. 创建并保存试卷基本信息状态为草稿
        Paper paper = new Paper();
        BeanUtils.copyProperties(aiPaperVo, paper);
        paper.setStatus("DRAFT");
        save(paper);
        log.info("本次{}试卷， 保存成功！", paper.getName());
        //  组卷规则下的试题和选择保存
        int questionCount = 0;
        BigDecimal totalScore = BigDecimal.ZERO;
        for (RuleVo rule : aiPaperVo.getRules()) {
            //步骤1：校验规则下的题目数量 = 0 跳过
            if (rule.getCount()  == 0) {
                log.warn("在：{}类型下，不需要出题！", rule.getType().name());
                continue;
            }
            //步骤2：查询当前规则下的所有题目集合 【type categoryIds】
            LambdaQueryWrapper<Question> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Question::getType, rule.getType().name());
            queryWrapper.in(!ObjectUtils.isEmpty(rule.getCategoryIds()), Question::getCategoryId, rule.getCategoryIds());
            List<Question> allQuestions = questionMapper.selectList(queryWrapper);
            //步骤3：校验查询的题目集合，集合为空！
            if (ObjectUtils.isEmpty(allQuestions)) {
                log.warn("在：{}类型下，没有题目！", rule.getType().name());
                continue;
            }
            //步骤4：判断下是否有规则下count数量！
            int realNumbers = Math.min(rule.getCount(), allQuestions.size());
            //步骤5：本次规则下添加的数量和分数累加
            questionCount += realNumbers;
            totalScore = totalScore.add(BigDecimal.valueOf((long) realNumbers * rule.getScore()));
            //步骤6：先打乱数据，再截取需要题目数量
            Collections.shuffle(allQuestions);
            List<Question> realQuestions = allQuestions.subList(0, realNumbers);
            //步骤7：转成中间表并进行保存
            List<PaperQuestion> paperQuestionsList = realQuestions.stream().map(question ->
                    new PaperQuestion(paper.getId().intValue(), question.getId(), BigDecimal.valueOf(rule.getScore()))
            ).collect(Collectors.toList());
            PaperQuestionService.saveBatch(paperQuestionsList);
        }
        //3. 修改试卷信息（总题数，总分数）
        paper.setQuestionCount(questionCount);
        paper.setTotalScore(totalScore);
        updateById(paper);
        //4. 返回试卷对象
        return paper;
    }

    @Override
    public void customUpdatePaperStatus(Integer id, String status) {
        if ("PUBLISHED".equals(status)) {
            LambdaQueryWrapper<PaperQuestion> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(PaperQuestion::getPaperId, id);
            long count = PaperQuestionService.count(queryWrapper);
            if (count == 0) {
                throw new RuntimeException("请先添加题目！");

            }
        }
        LambdaUpdateWrapper<Paper> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(Paper::getStatus, status);
        updateWrapper.eq(Paper::getId, id);
        update(updateWrapper);


    }

    // 删除试卷


    @Override
    public void customRemoveId(Integer id) {
        //不是发布状态
        Paper paper = getById(id);
        if (paper == null || "PUBLISHED".equals(paper.getStatus())) {
            throw new RuntimeException("发布状态下试卷无法删除！");
        }
        //不能有考试记录关联
        LambdaQueryWrapper<ExamRecord> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(ExamRecord::getExamId, id);
        Long count = examRecordMapper.selectCount(lambdaQueryWrapper);
        if (count > 0) {
            throw new RuntimeException("有考试记录关联，无法删除！");
        }
        //删除自身表
        removeById(Long.valueOf(id));
        //删除中间表
        PaperQuestionService.remove(new LambdaQueryWrapper<PaperQuestion>().eq(PaperQuestion::getPaperId, id));


    }


    //给与类型赋值
    private int typeToInt(String type) {
        switch (type) {
            case "CHOICE":
                return 1;
            case "JUDGE":
                return 2;
            case "TEXT":
                return 3;
            default:
                return 4;
        }

    }

}


